import serial
import json
import threading
from .version import Version
from .power import Power
from .adc import Adc
from .cpu import Cpu
from .led import Led
from .buzzer import Buzzer
from .io import Io
from .key import Key
from .pwm import Pwm
from .can import Can
from .rocker import Rocker
from .mpu import Mpu
from .card import Card
from .hmi import HMI
from .wifi import WIFI
from .servo import Servo
import app as robot_script

class Board:

    def __init__(self, framework):
        self.framework = framework
        self.status = False
        self.version = Version(self)
        self.power = Power(self)
        self.adc = Adc(self)
        self.cpu = Cpu(self)
        self.led = Led(self)
        self.io = Io(self)
        self.key = Key(self)
        self.buzzer = Buzzer(self)
        self.pwm = Pwm(self)
        self.can = Can(self)
        self.rocker = Rocker(self)
        self.mpu = Mpu(self)
        self.hmi = HMI(self)
        self.wifi = WIFI(self)
        self.servo = Servo(self)
        self.card = Card(self)
        self.func = dir(robot_script)
        self.serial = serial.Serial()
        self.serial_task = threading.Thread(name="task", target=self.task)
        self.serial_task.daemon = True

    def init(self):
        self.serial.port = self.framework.port
        self.serial.baudrate = 115200
        self.serial.bytesize = 8
        self.serial.stopbits = serial.STOPBITS_ONE
        self.serial.parity = serial.PARITY_NONE
        self.serial.timeout = 0.0023
        try:
            self.serial.open()
            self.status = True
            self.serial_task.start()
            self.framework.common.time.sleep(2)
            self.framework.common.socket.log("已经打开开发板串口：" + self.framework.port)
        except Exception as e:
            self.framework.common.socket.log("开发板串口打开失败：" + str(e))
            self.status = False

    def task(self):
        while True:
            if self.status:
                try:
                    read_data = self.read()
                    read_data_json = json.loads(read_data)
                    if read_data_json["type"] and read_data_json["type"] != "":
                        self.message_callback(read_data_json)
                except ValueError:
                    continue

    def write(self, data):
        if self.status:
            self.framework.common.time.sleep(0.023)
            self.serial.write(json.dumps(data).encode('utf-8'))

    def read(self):
        read_data = b""
        if self.status:
            self.framework.common.time.sleep(0.013)
            read_data = self.serial.readall()
        return read_data.decode('utf-8')

    def restart(self):
        command = {"type": "board-restart"}
        if self.status:
            self.write(command)

    def log(self, data):
        self.framework.common.socket.write(data)

    def close(self):
        if self.status:
            self.serial.close()
            self.status = False

    def message_callback(self, message):
        if message["type"] == "board-version":
            self.version.board_version = message["version"]
        if message["type"] == "adc-board-voltage":
            self.adc.voltage = message["voltage"]
        if message["type"] == "adc-pwm-voltage":
            self.adc.pwm_voltage = message["voltage"]
        if message["type"] == "cpu-temperature":
            self.cpu.temperature = message["temperature"]
        if message["type"] == "mpu-read":
            self.mpu.pit = message["pit"]
            self.mpu.yaw = message["yaw"]
            self.mpu.rol = message["rol"]
            self.mpu.temperature = message["temperature"]
            self.mpu.pressure = message["pressure"]
            self.mpu.altitude = message["altitude"]
        if message["type"] == "key-state":
            self.key.key_state = message["state"]
            func_str = "key_state_{}_event".format(message["state"])
            if func_str in self.func:
                getattr(robot_script, func_str)(self.framework)
        if message["type"] == "io-mode":
            func_str = "io_mode_channel_{}_data_{}_event".format(message["channel"], message["mode"])
            if func_str in self.func:
                getattr(robot_script, func_str)(self.framework)
        if message["type"] == "io-state":
            func_str = "io_state_channel_{}_data_{}_event".format(message["channel"], message["state"])
            if func_str in self.func:
                getattr(robot_script, func_str)(self.framework)
        if message["type"] == "rocker-control-data":
            self.rocker.ch0 = message["ch0"]
            self.rocker.ch1 = message["ch1"]
            self.rocker.ch2 = message["ch2"]
            self.rocker.ch3 = message["ch3"]
            self.rocker.ch4 = message["ch4"]
            self.rocker.s1 = message["s1"]
            self.rocker.s2 = message["s2"]
